home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / devel / vbcc-wos-src / vlink / support.c < prev    next >
C/C++ Source or Header  |  1999-01-01  |  11KB  |  492 lines

  1. /* $VER: vlink support.c V0.5e (05.10.98)
  2.  *
  3.  * This file is part of vlink, a portable linker for multiple
  4.  * object formats.
  5.  * Copyright (c) 1997-99  Frank Wille
  6.  *
  7.  * vlink is freeware and part of the portable and retargetable ANSI C
  8.  * compiler vbcc, copyright (c) 1995-99 by Volker Barthelmann.
  9.  * vlink may be freely redistributed as long as no modifications are
  10.  * made and nothing is charged for it. Non-commercial usage is allowed
  11.  * without any restrictions.
  12.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  13.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  14.  *
  15.  *
  16.  * v0.5e (05.10.98) phx
  17.  *       insertnode() is now insertbehind(). New functions insertbefore()
  18.  *       and addhead().
  19.  * v0.5d (22.08.98) phx
  20.  *       Faster allocation routines using large memory chunks. They must
  21.  *       be activated by #define FASTALLOC.
  22.  * v0.3  (12.04.98) phx
  23.  *       Replaced l2bh(),l2bw(),read16(),read32(),write16(),write32()
  24.  *       by swap16(),swap32(),read16sw(),read32sw(),write16sw(),write32sw().
  25.  *       fwrite32() is now called fwrite32be().
  26.  * v0.2  (07.03.98) phx
  27.  *       insertnode().
  28.  * v0.1  (27.02.98) phx
  29.  *       First version that seems to link AmigaOS ADOS and EHF
  30.  *       objects and libraries. Many common features, like linking
  31.  *       sections together which have relative references, are
  32.  *       still missing. Also, PowerPC-ELF32 support is about to come.
  33.  * v0.0  (04.08.97) phx
  34.  *       File created. Project started on a beautiful summer-day
  35.  *       at the North Sea beach of Cuxhaven. :)
  36.  *       This file is based on support.c v0.4 of the portable
  37.  *       PowerPC assembler "pasm".
  38.  */
  39.  
  40.  
  41. #define SUPPORT_C
  42. #include "vlink.h"
  43.  
  44.  
  45. void *alloc(size_t);
  46. void *alloczero(size_t);
  47. char *allocstring(char *);
  48. void *alloc_hashtable(size_t);
  49. void initlist(struct list *);
  50. void insertbefore(struct node *,struct node *);
  51. void insertbehind(struct node *,struct node *);
  52. void addhead(struct list *,struct node *);
  53. void addtail(struct list *,struct node *);
  54. struct node *remhead(struct list *);
  55. struct node *remnode(struct node *);
  56. char *mapfile(char *);
  57. char *base_name(char *);
  58. char *check_name(char *);
  59. int checkrange(uint32,int,bool);
  60. uint16 swap16(uint16);
  61. uint32 swap32(uint32);
  62. uint16 read16sw(uint8 *);
  63. uint32 read32sw(uint8 *);
  64. void write16sw(uint8 *,uint16);
  65. void write32sw(uint8 *,uint32);
  66. void fwritex(FILE *,void *,size_t);
  67. void fwrite32be(FILE *,uint32);
  68. void fwrite_align(FILE *,uint32,uint32);
  69. unsigned long elf_hash(unsigned char *);
  70. unsigned long align(unsigned long,unsigned long);
  71. int shiftval(uint32);
  72.  
  73. static size_t filesize(FILE *,char *);
  74.  
  75. static char *unnamed_txt = "unnamed";
  76.  
  77.  
  78. #ifdef FASTALLOC
  79. static struct MemChunk *new_chunk(void);
  80. void init_mem(void);
  81.  
  82. #define CHUNKSIZE (0x40000-sizeof(void *)-sizeof(void *)-8)
  83.  
  84. struct MemChunk {             /* Large memory chunks for faster allocation */
  85.   struct MemChunk *next;
  86.   unsigned char *ptr;         /* pointer to available memory in this chunk */
  87.   uint32 free;                /* number of bytes free */
  88. #ifndef ALIGNOFF4
  89.   uint32 align;               /* only for 64-bit alignment */
  90. #endif
  91.   unsigned char mchunk[CHUNKSIZE];
  92. };
  93.  
  94. static struct MemChunk *mem;  /* first memory chunk for alloc() */
  95.  
  96.  
  97.  
  98. static struct MemChunk *new_chunk()
  99. {
  100.   struct MemChunk *m;
  101.  
  102.   if (!(m = (struct MemChunk *)malloc(sizeof(struct MemChunk))))
  103.     error(1);  /* out of memory */
  104.   m->next = NULL;
  105.   m->ptr = m->mchunk;
  106.   m->free = CHUNKSIZE;
  107.   return (m);
  108. }
  109.  
  110.  
  111. void init_mem()
  112. {
  113.   mem = new_chunk();
  114. }
  115. #endif
  116.  
  117.  
  118. void *alloc(size_t size)
  119. /* allocate memory and print error message if not enough available */
  120. {
  121. #ifdef FASTALLOC  /* faster, but needs more memory */
  122.   struct MemChunk *m=mem,*n;
  123.   uint32 bytes;
  124.   void *p;
  125.  
  126.   if (!(bytes = (uint32)(size+7) & ~7))  /* return 64-bit aligned memory */
  127.     bytes = 8;
  128.   if (bytes > CHUNKSIZE) {
  129.     /* get an own block, for so much memory */
  130.     if (!(p = malloc((size_t)bytes)))
  131.       error(1);  /* out of memory */
  132.     return (p);
  133.   }
  134.   for (;;) {
  135.     if (bytes <= m->free) {
  136.       p = (void *)m->ptr;
  137.       m->free -= bytes;
  138.       m->ptr += bytes;
  139.       return (p);
  140.     }
  141.     if (!(n = m->next))
  142.       n = m->next = new_chunk();
  143.     m = n;
  144.   }
  145.  
  146. #else
  147.   void *p;
  148.  
  149.   if (!size)
  150.     size = 1;
  151.   if (!(p = malloc(size)))
  152.     error(1);  /* out of memory */
  153.   return (p);
  154. #endif
  155. }
  156.  
  157.  
  158. void *alloczero(size_t size)
  159. /* same as alloc() but zeroes the allocated memory */
  160. {
  161.   void *p = alloc(size);
  162.  
  163.   memset(p,0,size);
  164.   return (p);
  165. }
  166.  
  167.  
  168. char *allocstring(char *s)
  169. /* allocate space for a single string */
  170. /* @@@ this should be improved by some kind of string buffer */
  171. {
  172.   char *p = alloc(strlen(s)+1);
  173.  
  174.   strcpy(p,s);
  175.   return (p);
  176. }
  177.  
  178.  
  179. void *alloc_hashtable(size_t entries)
  180. {
  181.   return (alloczero(entries * sizeof(void *)));
  182. }
  183.  
  184.  
  185. void initlist(struct list *l)
  186. /* initializes a list structure */
  187. {
  188.   l->first = (struct node *)&l->dummy;
  189.   l->dummy = NULL;
  190.   l->last = (struct node *)&l->first;
  191. }
  192.  
  193.  
  194. void insertbefore(struct node *n,struct node *sn)
  195. /* insert node n directly before node sn */
  196. /* sn must be a real node - no dummy nodes allowed! */
  197. {
  198.   struct node *pn = sn->pred;
  199.  
  200.   n->next = sn;
  201.   n->pred = pn;
  202.   pn->next = sn->pred = n;
  203. }
  204.  
  205.  
  206. void insertbehind(struct node *pn,struct node *n)
  207. /* insert node n directly behind node pn */
  208. /* pn must be a real node - no dummy nodes allowed! */
  209. {
  210.   struct node *sn = pn->next;
  211.  
  212.   n->next = sn;
  213.   n->pred = pn;
  214.   pn->next = sn->pred = n;
  215. }
  216.  
  217.  
  218. void addhead(struct list *l,struct node *n)
  219. /* add node as first element of list */
  220. {
  221.   struct node *fn = l->first;
  222.  
  223.   n->pred = fn->pred;
  224.   fn->pred = n;
  225.   n->next = fn;
  226.   l->first = n;
  227. }
  228.  
  229.  
  230. void addtail(struct list *l,struct node *n)
  231. /* add node as last element of list */
  232. {
  233.   struct node *ln = l->last;
  234.  
  235.   n->next = ln->next;
  236.   ln->next = n;
  237.   n->pred = ln;
  238.   l->last = n;
  239. }
  240.  
  241.  
  242. struct node *remhead(struct list *l)
  243. /* remove first node in list and return a pointer to it */
  244. {
  245.   struct node *n = l->first;
  246.  
  247.   if (n->next) {
  248.     l->first = n->next;
  249.     n->next->pred = n->pred;
  250.     return (n);
  251.   }
  252.   return (NULL);
  253. }
  254.  
  255.  
  256. struct node *remnode(struct node *n)
  257. /* remove a node from a list */
  258. {
  259.   n->next->pred = n->pred;
  260.   n->pred->next = n->next;
  261.   return (n);
  262. }
  263.  
  264.  
  265. char *mapfile(char *name)
  266. /* map a complete file into memory and return its address */
  267. /* the file's length is returned in *(p-sizeof(size_t)) */
  268. {
  269.   FILE *fp;
  270.   char *p=NULL;
  271.   size_t fsiz;
  272.  
  273.   if (fp = fopen(name,"r")) {
  274.     fsiz = filesize(fp,name);
  275.     p = alloc(fsiz+sizeof(size_t));
  276.     *(size_t *)p = fsiz;  /* store file size before the text starts */
  277.     p += sizeof(size_t);
  278.     if (fread(p,1,fsiz,fp) != fsiz) {
  279.       fclose(fp);
  280.       error(7,name);  /* read error */
  281.     }
  282.     fclose(fp);
  283.   }
  284.   return (p);
  285. }
  286.  
  287.  
  288. static size_t filesize(FILE *fp,char *name)
  289. {
  290.   /* somebody knows a better way to determine file size in ANSI C? */
  291.   long oldpos,size;
  292.  
  293.   if ((oldpos = ftell(fp)) >= 0)
  294.     if (fseek(fp,0,SEEK_END) >= 0)
  295.       if ((size = ftell(fp)) >= 0)
  296.         if (fseek(fp,oldpos,SEEK_SET) >= 0)
  297.           return ((size_t)size);
  298.   fclose(fp);
  299.   error(5,name);  /* read error - doesn't return */
  300. }
  301.  
  302.  
  303. char *base_name(char *s)
  304. /* returns last part of a path - the file name itself */
  305. {
  306.   char c;
  307.   int l = strlen(s);
  308.  
  309.   while (l--) {
  310.     c = s[l];
  311.     if (c== '/' || c==':')
  312.       return (&s[l+1]);
  313.   }
  314.   return (s);
  315. }
  316.  
  317.  
  318. char *check_name(char *name)
  319. /* returns "unnamed", if name is a NULL-pointer */
  320. {
  321.   if (name)
  322.     return (name);
  323.   return (unnamed_txt);
  324. }
  325.  
  326.  
  327. int checkrange(uint32 val,int size,bool sign)
  328. /* Checks if an integer value is in range, size=3 means 26-bit (B-instr.) */
  329. /* If the check fails, the number of bits is returned (8, 16, 26) */
  330. {
  331.   if (sign) {
  332.     int32 sval = (int32)val;
  333.     switch (size) {
  334.       case 1:
  335.         if (sval>0x7f || sval<-0x80)
  336.           return (8);
  337.         break;
  338.       case 2:
  339.         if (sval>0x7fff || sval<-0x8000)
  340.           return (16);
  341.         break;
  342.       case 3:
  343.         if (sval>0x1ffffff || sval<-0x2000000)
  344.           return (26);
  345.         break;
  346.     }
  347.   }
  348.   else {
  349.     switch (size) {
  350.       case 1:
  351.         if (val>0xff)
  352.           return (8);
  353.         break;
  354.       case 2:
  355.         if (val>0xffff)
  356.           return (16);
  357.         break;
  358.       case 3:
  359.         if (val>0x3ffffff)
  360.           return (26);
  361.         break;
  362.     }
  363.   }
  364.   return (0);
  365. }
  366.  
  367.  
  368. uint16 swap16(uint16 x)
  369. /* 16-bit endian conversion */
  370. {
  371.   return ((x&0xff)<<8 | (x&0xff00)>>8);
  372. }
  373.  
  374.  
  375. uint32 swap32(uint32 x)
  376. /* 32-bit endian conversion */
  377. {
  378.   return ((x&0xff)<<24 | (x&0xff00)<<8 |
  379.           (x&0xff0000)>>8 | (x&0xff000000)>>24);
  380. }
  381.  
  382.  
  383. uint16 read16sw(uint8 *p)
  384. /* read 16 bit word with endian conversion */
  385. {
  386.   return (((uint16)*p)<<8 | ((uint16)*(p+1)));
  387. }
  388.  
  389.  
  390. uint32 read32sw(uint8 *p)
  391. /* read 32 bit word with endian conversion */
  392. {
  393.   return (((uint32)*p)<<24 | ((uint32)*(p+1))<<16 |
  394.           ((uint32)*(p+2))<<8 | ((uint32)*(p+3)));
  395. }
  396.  
  397.  
  398. void write16sw(uint8 *p,uint16 x)
  399. /* write 16 bit word with endian conversion */
  400. {
  401.   *p++ = (uint8)((x>>8)&0xff);
  402.   *p = (uint8)(x&0xff);
  403. }
  404.  
  405.  
  406. void write32sw(uint8 *p,uint32 x)
  407. /* write 32 bit word with endian conversion */
  408. {
  409.   *p++ = (uint8)((x>>24)&0xff);
  410.   *p++ = (uint8)((x>>16)&0xff);
  411.   *p++ = (uint8)((x>>8)&0xff);
  412.   *p = (uint8)(x&0xff);
  413. }
  414.  
  415.  
  416. void fwritex(FILE *fp,void *buf,size_t len)
  417. /* write a buffer of len bytes, with check for len=0 and write error */
  418. {
  419.   if (len) {
  420.     if (!fwrite(buf,1,len,fp)) {
  421.       fclose(fp);
  422.       error(31,gvars.dest_name);  /* write error */
  423.     }
  424.   }
  425. }
  426.  
  427.  
  428. void fwrite32be(FILE *fp,uint32 w)
  429. /* write a big endian 32 bit word */
  430. {
  431.   uint32 be = ECVW(w);
  432.  
  433.   if (!fwrite(&be,1,sizeof(uint32),fp)) {
  434.     fclose(fp);
  435.     error(31,gvars.dest_name);  /* write error */
  436.   }
  437. }
  438.  
  439.  
  440. void fwrite_align(FILE *fp,uint32 a,uint32 n)
  441. /* writes as many zero bytes as required for alignment a (a bits */
  442. /* must be zero) with current file offset n */
  443. {
  444.   static uint8 alignment_bytes[MAX_FWALIGN];
  445.  
  446.   a = 1<<a;
  447.   if ((n = (a-(n&(a-1))&(a-1))) > MAX_FWALIGN)
  448.     ierror("fwrite_align(): Alignment > %d required",MAX_FWALIGN);
  449.   fwritex(fp,alignment_bytes,n);
  450. }
  451.  
  452.  
  453. unsigned long elf_hash(unsigned char *name)
  454. /* calculate a hash code as used in ELF objects */
  455. {
  456.   unsigned long h=0,g;
  457.  
  458.   while (*name) {
  459.     h = (h << 4) + *name++;
  460.     if (g = h & 0xf0000000)
  461.       h ^= g >> 24;
  462.     h &= ~g;
  463.   }
  464.   return (h);
  465. }
  466.  
  467.  
  468. unsigned long align(unsigned long addr,unsigned long alignment)
  469. /* return number of bytes required to achieve alignment */
  470. {
  471.   unsigned long a = (1<<alignment) - 1;
  472.  
  473.   return (((addr+a)&~a) - addr);
  474. }
  475.  
  476.  
  477. int shiftval(uint32 x)
  478. /* returns number of 0-bits before the first 1-bit - something like */
  479. /* an integer-log2() function - returns 0 on x=0 */
  480. {
  481.   int i;
  482.  
  483.   if (x == 0)
  484.     return (0);
  485.   for (i=0; i<32; i++) {
  486.     if (x & 1)
  487.       break;
  488.     x >>= 1;
  489.   }
  490.   return (i);
  491. }
  492.